// 定义过滤器
Vue.filter('formateDate', function(msg) {
    // 格式化好友列表里面的时间
    function formateDate(end_time) {
        var end_str = end_time.replace(/-/g, "/");
        var end_date = new Date(end_str); //将字符串转化为时间 

        var now_str = new Date().toLocaleDateString() + ' 23:59:59';
        var now_date = new Date(now_str);
        var num = (now_date - end_date) / (1000 * 3600 * 24);
        if (num < 1) {
            return end_date.getHours() + ':' + end_date.getMinutes();
        } else if (num >= 1 && num < 2) {
            return '昨天';
        } else {
            return end_date.toLocaleDateString();
        }
    }

    // 执行
    return formateDate(msg);
})

const app = new Vue({
    el: "#chat",
    data: {
        username: "",
        userPicture: "",
        searchInfo: "",
        isShow:'none',
        // 获取到的好友列表
        friendsList: [],
        // 搜索框显示标志
        flagOfSearch: true,
        // focus类
        focusID: '-1',
        // 存一下当前点击的好友的名字
        currentFriendName: '',
        // 存一下当前点击好友的头像
        currentFriendPic: '',
        // 存储和当前好友的聊天记录
        currentChatHistory: [],
        // 存储和当前聊天的linkId
        linkId: '',
        // 存储聊天框里面的值
        msgContent: '',
        // 存储聊天记录的总页数
        totalHistoryNum: 1,
        // 在查看历史记录的时候有新消息
        hasUnread: false,
        //layui加载框对象
        load: null,
        // 即时聊天websocket
        websocket: null,
        //是否真正建立连接
        lockReconnect: false,
        //30秒一次心跳
        timeout: 28 * 1000,
        //外层心跳倒计时
        timeoutObj: null,
        //内层心跳检测
        serverTimeoutObj: null,
        //断开 重连倒计时
        timeoutnum: null

    },


    created() {
        this.getCurrentUserInfo();
        this.getChatList();
        // 初始化webSocket
        this.initWebSocket();
        // 对url地址进行解析
        var map = this.getUrlParam();
        if (map != null) {
            // 如果不为null 则说明是从别的地方点进来的  而不是直接进入聊天界面 此时需要判断聊天列表有没有这个人
            var path = '/chat/adminCheckIsFirstChat?toUser=' + map.toUser;
            var friendName = map.toUser;
            axios.get(path).then(async res => {
                if (res.data.status == '0') {
                    // 如果返回值是0 说明不是第一次聊天 直接定位到这个人的聊天记录几个
                    this.$nextTick(() => {
                        // 获取到当前用户的dom节点
                        this.$refs[friendName][0].click();
                    });
                } else if (res.data.status == '1') {
                    // 如果返回值是1 说明是第一次聊天 需要先建立连接 然后重新刷新好友列表 然后在定位到这个人
                    await this.getChatList();
                    this.$nextTick(() => {
                        // 获取到当前用户的dom节点
                        this.$refs[friendName][0].click();
                    });
                }
            }).catch(err => {
                console.log(err);
            })

        }
    },
    methods: {
        // 封装函数 返回地址栏中的参数
        getUrlParam: function() {
            // 获取地址栏的东西 看看是要做什么事情
            var path = location.href;
            if (path.indexOf('?') != -1) {
                // 说明有参数
                // 对path进行解析 用问号分隔
                var arr = path.split('?')[1];
                arr = arr.split('&');
                var map = {};
                for (var i = 0; i < arr.length; i++) {
                    var keyAndVal = arr[i].split('=');
                    //对中文字符进行解码,获取到中文字符
                    keyAndVal[1] = decodeURIComponent(keyAndVal[1]);
                    map[keyAndVal[0]] = keyAndVal[1];
                }
                return map;
            } else {
                return null;
            }

        },
        // 初始化webSocket
        initWebSocket: function() {
            //TODO 这个地址需要修改
            const target = "ws://localhost:8081/websocket";

            //判断当前浏览器是否支持WebSocket
            if ('WebSocket' in window) {
                this.websocket = new WebSocket(target);
            } else {
                console.log('Not support websocket');
            };
            //连接发生错误的回调方法
            this.websocket.onerror = () => {
                this.initWebSocket();
                console.log('连接发生错误！')
            };
            //连接关闭的回调方法
            this.websocket.onclose = () => {
                console.log('关闭连接！');
            };

            //连接成功建立的回调方法
            this.websocket.onopen = (event) => {
                console.log('连接成功！')
            };
            //接收到消息的回调方法
            this.websocket.onmessage = (event) => {
                // data: "{"sendUser":"admin","content":"hhh","sendTime":1617023867997}"
                var chatContent = JSON.parse(event.data);
                this.reset();
                console.log(chatContent);
                // 判断是从哪里发过来的 如果是正在聊天的那个娃 就直接添加到正在聊天的历史记录的数组中
                if (chatContent.sendUser == this.currentFriendName) {
                    // 如果文档的高度-折叠起来的高度 == clientHeight 
                    // 就是没有滚动 直接拉到底部
                    // 如果文档的高度-折叠起来的高度 > clientHeight+10px 在查看历史记录状态
                    // else  就是在底部的状态 直接拖到底

                    // 记住当前正在浏览的历史记录的bottom
                    var scBottom = 0;
                    var isScanHistory = false;
                    this.$nextTick(() => {
                        var container = this.$el.querySelector("#chatContainer");
                        if (container.scrollHeight - container.scrollTop > container.clientHeight) {
                            // 表示在查看历史记录  显示按钮  并保持不动
                            isScanHistory = true;
                            // 记住当前正在浏览的历史记录的bottom
                            scBottom = container.scrollHeight - container.scrollTop - container.offsetHeight;
                        }
                    });
                    console.log(isScanHistory);

                    // 将消息放进去对应的数组中
                    // 这里要格式化时间
                    chatContent.sendTime = this.dateFormat(chatContent.sendTime, 'yyyy-mm-dd hh:mm:ss')
                    this.currentChatHistory.push(chatContent);

                    // 放进去之后 根据是否是在浏览历史记录 来做不同的处理
                    this.$nextTick(() => {
                        var container = this.$el.querySelector("#chatContainer");
                        if (isScanHistory) {
                            // 表示在查看历史记录  显示按钮  并保持不动
                            container.scrollTop = container.scrollHeight - container.offsetHeight - scBottom;
                            this.hasUnread = true;
                        } else {
                            // 表示处于聊天整天 直接拉到底部
                            container.scrollTop = container.scrollHeight;
                            this.hasUnread = false;
                        }
                    });

                    // 设置上一条消息
                    var index = this.friendsList.findIndex(item => {
                        return item.friendName == this.currentFriendName;
                    });
                    if (index != -1) {
                        this.$set(this.friendsList[index], 'lastMessage', chatContent.content);
                    } else {
                        console.log('有经过的消息未设置为上一条消息！' + chatContent);
                    }
                } else {
                    // 如果不是正在聊天的那个人 就将该user的未读消息+1
                    // 查找对应的friend的下标
                    var index = this.friendsList.findIndex(item => {
                        return item.friendName == chatContent.sendUser;
                    });
                    if (index != -1) {
                        // 说明找到了 将其的unread+1
                        this.$set(this.friendsList[index], 'unread', parseInt(this.friendsList[index].unread) + 1);
                        console.log(parseInt(this.friendsList[index].unread) + 1);
                        // 设置当前好友的上一条消息为这个
                        this.$set(this.friendsList[index], 'lastMessage', chatContent.content);

                    } else {
                        console.log('发出去的消息经过这里了！' + chatContent);
                    }
                }

            };

            //监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
            window.onunload = async() => {
                var url = '/chat/resetAdminWindows';
                await axios.get(url);
            };
        },

        // 重新连接
        reconnect() {
            //重新连接
            var that = this;
            if (that.lockReconnect) {
                // 是否真正建立连接
                return;
            }
            that.lockReconnect = true;
            //没连接上会一直重连，设置延迟避免请求过多
            that.timeoutnum && clearTimeout(that.timeoutnum);
            // 如果到了这里断开重连的倒计时还有值的话就清除掉
            that.timeoutnum = setTimeout(function() {
                //然后新连接
                that.initWebSocket();
                that.lockReconnect = false;
            }, 5000);
        },

        //重置心跳
        reset() {
            var that = this;
            //清除时间（清除内外两个心跳计时）
            clearTimeout(that.timeoutObj);
            clearTimeout(that.serverTimeoutObj);
            //重启心跳
            that.start();
        },

        start() {
            //开启心跳
            var self = this;
            self.timeoutObj && clearTimeout(self.timeoutObj);
            // 如果外层心跳倒计时存在的话，清除掉
            self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
            // 如果内层心跳检测倒计时存在的话，清除掉
            self.timeoutObj = setTimeout(function() {
                // 重新赋值重新发送 进行心跳检测
                //这里发送一个心跳，后端收到后，返回一个心跳消息，
                if (self.websocket.readyState == 1) {
                    //如果连接正常
                    // self.websock.send("heartCheck");
                } else {
                    //否则重连
                    self.reconnect();
                }
                self.serverTimeoutObj = setTimeout(function() {
                    // 在三秒一次的心跳检测中如果某个值3秒没响应就关掉这次连接
                    //超时关闭
                    self.websocket.close();
                }, self.timeout);
            }, self.timeout);
            // 3s一次
        },

        // 使用websocket发送消息
        websocketSend: function() {
            var chatMsg = {
                content: this.msgContent,
                toUser: this.currentFriendName,
                linkId: this.linkId
            };
            // 发送消息
            this.websocket.send(JSON.stringify(chatMsg));
            // 添加sendUser属性 然后添加到本来的列表中
            chatMsg.sendUser = this.username;
            // 格式化日期
            chatMsg.sendTime = this.dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss');
            // 添加進去聊天历史列表
            this.currentChatHistory.push(chatMsg);

            // 设置上一条消息为这一条 暂时不确定 应该不需要这个
            var index = this.friendsList.findIndex(item => {
                return item.friendName == this.currentFriendName;
            });
            if (index != -1) {
                // 说明找到了 将其的unread+1
                this.$set(this.friendsList[index], 'lastMessage', this.msgContent);
            } else {
                console.log('没有将这个发出去的消息设置为未读消息那里！！' + chatMsg);
            }

            // 清空输入内容框
            this.msgContent = '';
            // 将历史记录滚动到底部
            this.scrollBottom();

        },

        //获取当前用户的用户名和头像
        getCurrentUserInfo: function() {
            axios.get("/adminIsLogin").then(response => {
                //获取json数据
                let resultInfo = response.data;
                this.username = resultInfo.data.username
                this.userPicture = resultInfo.data.userPicture;
                console.log(this.userPicture);
            }).catch();
        },

        //获取当前用户的聊天列表
        getChatList: function() {
            var url = "/chat/getAdminChatList";
            // 声明加载框对象
            this.load = layer.load({ time: 2000 });
            axios.get(url)
                .then(res => {
                    //获取json数据
                    if (res.data.status == '1') {
                        this.friendsList = res.data.data;
                        layer.close(this.load);
                    }
                }).catch(err => {
                    console.log(err);
                });
        },

        // 当点击用户想要打开对话框时 发送下面两个请求 拿历史记录、建立连接
        getHistory: function(friendName) {
            this.load = layer.load({ time: 2000 });
            var url = '/chat/getAdminChatRecords/' + friendName + '?startIndex=0&pageSize=6';
            axios.get(url).then(res => {
                if (res.data.status == '1') {
                    layer.close(this.load);
                    this.currentChatHistory = res.data.data;
                    // 滚动到底部
                    this.scrollBottom();
                }
            })
        },

        // 向上滚动获取历史记录
        scrollHistory: async function(event) {
            var sHeight = 0;
            this.$nextTick(() => {
                var container = this.$el.querySelector("#chatContainer");
                // 记住当前文档的高度
                sHeight = container.scrollHeight;
            });
            if (event.target.scrollTop == 0) {
                // 更新聊天记录
                // 当前有多少条记录
                var currentIndex = this.currentChatHistory.length;
                var pageSize = 6;
                var url = '/chat/getAdminChatRecords/' + this.currentFriendName + '?startIndex=' + currentIndex + '&pageSize=' + pageSize;
                var history = await axios.get(url);
                var tempHistory = history.data.data;
                this.currentChatHistory = tempHistory.concat(this.currentChatHistory);

                this.$nextTick(() => {
                    var container = this.$el.querySelector("#chatContainer");
                    // 当前文档总高度-刚刚记录的文档的高度 就是需要被折叠起来的高度
                    container.scrollTop = container.scrollHeight - sHeight;
                });
            }
            // 滚动到底部时 自动消失那个提示框
            this.$nextTick(() => {
                var container = this.$el.querySelector("#chatContainer");
                if (container.scrollHeight - container.scrollTop <= container.clientHeight) {
                    this.hasUnread = false;
                }
            });


        },

        // 聊天记录滚动到底部实现
        scrollBottom: function() {
            setTimeout(() => {
                this.$nextTick(() => {
                    var container = this.$el.querySelector("#chatContainer");
                    container.scrollTop = container.scrollHeight;
                    this.hasUnread = false;
                });
            }, 0);
        },

        // 隐藏显示是否滚动到下面的按钮
        hideUnreadBtn: function() {
            this.hasUnread = false;
        },

        // 聊天记录滚动到底部实现
        scrollBottom: function() {
            setTimeout(() => {
                this.$nextTick(() => {
                    var container = this.$el.querySelector("#chatContainer");
                    container.scrollTop = container.scrollHeight;
                    this.hasUnread = false;
                });
            }, 0);
        },

        // 隐藏显示是否滚动到下面的按钮
        hideUnreadBtn: function() {
            this.hasUnread = false;
        },

        // 跟对方建立连接 判断对方是否在线
        getStaus: function(friendName) {
            var url = '/chat/AdminInWindows/' + friendName;
            axios.get(url).then(res => {

                // 建立连接的同时会把全部消息设置为已读 这个因为没有重新去请求后台，所以自己做一个就行
                var index = this.friendsList.findIndex(item => {
                    return item.friendName == friendName;
                });
                // console.log(index);
                this.$set(this.friendsList[index], 'unread', 0);
            })

        },

        // 用来绑定点击不同的元素展示不同的样式,同时记录一下东西
        itemFoucs: function(index, item) {
            // 记录当前的index 用来渲染css样式
            this.focusID = index;
            // 输入消息的对话框自动对焦
            this.$nextTick(function() {
                //DOM 更新了
                this.$refs.messageInput.focus();
            });
            // 记住当前聊天的好友
            this.currentFriendName = item.friendName;
            // 记住当前聊天好友的头像
            this.currentFriendPic = item.friendPicture;

            // 记住当前好友的linkID
            this.linkId = item.linkId;
            // 如果当前点击的人不在页面内 需要定位到页面内 用于从别处过来的页面的请求
            this.$nextTick(() => {
                // 获取到当前用户的dom节点
                var friendName = item.friendName;
                // 当前的好友
                var curFriend = this.$refs[friendName][0];
                // 好友列表
                var friends = this.$refs.friendList;
                if (curFriend.offsetTop < friends.scrollTop || curFriend.offsetTop > friends.scrollTop + friends.clientHeight) {
                    // 表明不在窗口内 需要定位到顶部
                    friends.scrollTop = curFriend.offsetTop;
                }
            });

        },

        // 当点击上面的小搜索框 需要展示出大的搜索框
        showBigSearch: function() {
            this.flagOfSearch = false;
            this.$nextTick(function() {
                //DOM 更新了
                this.$refs.inputVal.focus()
            })
        },

        // 当失去焦点 或者按下enter的时候显示小的搜索框
        showSmallSearch: function() {
            this.flagOfSearch = true;
            this.searchInfo = this.$refs.inputVal.value
            if(this.searchInfo !== "" && this.searchInfo !== this.username){
                axios.get("/searchUser/"+ this.searchInfo).then(response => {
                    const resultInfo = response.data;
                    var url = "/adminChat?toUser=" + resultInfo.data.username;
                    location.href = url;

                }).catch();
            } else if(this.searchInfo === this.username){
                layer.msg("不允许自己与自己聊天", { time: 1500 });
            } else {
                layer.msg("该用户不存在", { time: 1500 });
            }


        },
        showMenu: function() {
            this.isShow = 'block';
        },
        hiddenMenu: function() {
            this.isShow = 'none';

        },
        skip_user:function(toUser){
            var url = "/user.html?toUser=" + toUser;
            location.href = url;
        },

        // 格式化日期
        dateFormat: function(date, format) {
            if (typeof date === "string") {
                var mts = date.match(/(\/Date\((\d+)\)\/)/);
                if (mts && mts.length >= 3) {
                    date = parseInt(mts[2]);
                }
            }
            date = new Date(date);
            if (!date || date.toUTCString() == "Invalid Date") {
                return "";
            }
            var map = {
                "M": date.getMonth() + 1, //月份 
                "d": date.getDate(), //日 
                "h": date.getHours(), //小时 
                "m": date.getMinutes(), //分 
                "s": date.getSeconds(), //秒 
                "q": Math.floor((date.getMonth() + 3) / 3), //季度 
                "S": date.getMilliseconds() //毫秒 
            };

            format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
                var v = map[t];
                if (v !== undefined) {
                    if (all.length > 1) {
                        v = '0' + v;
                        v = v.substr(v.length - 2);
                    }
                    return v;
                } else if (t === 'y') {
                    return (date.getFullYear() + '').substr(4 - all.length);
                }
                return all;
            });
            return format;
        }
    },
})